const code_types = {
    "brand_skus": {
        pattern: "code_pattern_brand_skus",
        seq: "code_seq_brand_skus",
        default: "${format(date(now),'YYYYMMDD')}${pad(seq,6)}"
    },
    "trader_skus": {
        pattern: "code_pattern_trader_skus",
        seq: "code_seq_trader_skus",
        default: "${format(date(now),'YYYYMMDD')}${pad(seq,6)}"
    }
}

module.exports = function(lab) {
    return {
        // 详见 slime_brands 这张表， 根据ouid和name获取brand, 如果不存在brand， 那么就创建一个
        // WynnREADME : 这里不需要开启snapshot, snapshot是数据库事务，通常会锁定数据库，
        // snapshot的使用场景是为了处理一整条链的行为，如果后续行为可能会需要前面的数据库操作回滚的话，用snapshot
        @getBrandByName: function(ouid, name) {

            return lab.sqlite.find("slime_brands", {
                "ouid": ouid,
                "name": name
            }).then(function(brand) {

                if (brand.records.length) {
                    this.next(brand.records[0]);
                } else {

                    lab.create("slime_brands", {
                        "id": @.uuid(),
                        "ouid": ouid,
                        "name": name,
                        "is_removed": false
                    }).pipe(this);

                }
            })
        },

        // 详见 slime_categories 这张表， 根据ouid和name获取category, 如果不存在category， 那么就创建一个
        @getCategoryByName: function(ouid, name) {

            return lab.sqlite.find("slime_categories", {
                "ouid": ouid,
                "name": name
            }).then(function(category) {

                if (category.records.length) {
                    this.next(category.records[0]);
                } else {

                    lab.create("slime_categories", {
                        "id": @.uuid(),
                        "ouid": ouid,
                        "name": name,
                        "is_removed": false
                    }).pipe(this);

                }
            })
        },

        @getImageURLFromFTPPath: function(session, candidates) {

            return @.async(function() {

                if (candidates && Array.isArray(candidates) && candidates.length && lab.ftp) {

                    lab.ftp.@getUserHomeDir(session).then(function(homeDirPath) {

                        var fullPath = candidates.reduce(function(result, candidate) {

                            var filePath = @.fs.realOSPath(homeDirPath, candidate)

                            if (!result && @.fs.exists.file(filePath)) {
                                result = filePath;
                            }

                            return result;
                        }, null);

                        if (fullPath) {

                            lab.uploader.qiniu.@uploadFile(fullPath, {
                                key: @.fs.fileMD5(fullPath) + @.fs.extname(fullPath),
                                needCover: true
                            }).pipe(this);

                        } else {
                            this.next();
                        }

                    }).pipe(this);
                } else {
                    this.next();
                }
            })
        },
        @getSettings: function() {
            return lab.sqlite.find("slime_system_settings", {

            }).then(function(result) {

                if (result.records.length) {
                    this.next(result.records.reduce(function(cvalue, pair) {
                        cvalue[pair.key] = pair.value;
                        return cvalue;
                    }, {}));
                } else {
                    this.next({});
                }

            }).then(function(settings) {

                this.next(@.merge.advanced({
                    "id": {
                        "!valueType": "string",
                        "!defaultValue": @.uuid()
                    }
                }, settings));

            });
        },
        @getOUSettings: function(ouid) {
            if (!ouid) {
                throw @lab.errors.invalid_parameters;
            }
            return lab.find("slime_operation_unit_settings", ouid).then(function(settings) {

                if (settings) {

                    this.next(settings);

                } else {

                    var default_settings = {
                        id: ouid,
                        coupon_types: @.keys(@lab.constants.coupon_types),
                        activity_types: @.keys(@lab.constants.activity_types),
                        consume_types: @.keys(@lab.constants.consume_types),
                        activity_external_sources: @.keys(@lab.constants.activity_external_sources),
                    };

                    @.keys(code_types).forEach(function(type) {

                        var code_type = code_types[type];

                        default_settings[code_type.seq] = 0;
                        default_settings[code_type.pattern] = code_type.default;

                    });

                    lab.create("slime_operation_unit_settings", default_settings).pipe(this);
                }
            })
        },

        @generateNextCode: function(ouid, { pattern, type }) {
            var code_type = code_types[type];

            if (!code_type) {
                throw @lab.errors.invalid_parameters;
            }

            return lab.snapshot(function(snapshot) {

                return snapshot.slime.core.@getOUSettings(ouid).then(function(settings) {

                    var pattern = pattern || settings[code_type.pattern] || code_type.default;
                    var seq = settings[code_type.seq] + 1;
                    var now = Date.now();

                    var code = @.format(pattern, {
                        seq: seq + 1,
                        now: now
                    }, {
                        functors: {
                            pad: function(a1, a2, a3, a4, value, length) {
                                return @.format.zero(value, length);
                            }
                        }
                    });

                    settings[code_type.seq] = seq;
                    snapshot.update("slime_operation_unit_settings", settings).resolve(code).pipe(this);

                })
            })
        },
        "getImageInfo": function(session, imageURL) {
            if (!session.currentUser) {
                throw @lab.errors.not_login;
            }

            // if (!imageURL || imageURL.indexOf(new Uploader(@options("upload")).baseURL) < 0) {
            //     throw @lab.errors.invalid_parameters;
            // }

            var handler = require(imageURL.substr(0, imageURL.indexOf(":")));
            return @.async(function() {
                handler.get(imageURL + "?imageInfo", this.next);
            }).then(function(response) {

                var json = [];
                response.on("data", (chunk) => {
                    json.push(chunk);
                });

                response.on("error", (error) => {
                    this.reject(new HTTPError(415, "Failed to read request, " + error.message));
                });

                response.on("end", () => {

                    if (0 != json.length) {

                        try {
                            this.next(JSON.parse(json.join("")));
                        } catch (ex) {
                            this.reject(ex);
                        }

                    } else {
                        this.reject("post body not found");
                    }

                });
            });
        }
    }
}
